package com.douqu.game.core.entity.ext.data.challenge;

import com.bean.core.buffer.ByteBuffer;
import com.douqu.game.core.config.VipConfig;
import com.douqu.game.core.config.goods.PropConfig;
import com.douqu.game.core.config.map.CityDropGroupConfig;
import com.douqu.game.core.e.E_CityDrop_Flush_Type;
import com.douqu.game.core.e.E_WorldMapKillRankType;
import com.douqu.game.core.entity.Player;
import com.douqu.game.core.entity.common.TwoTuple;
import com.douqu.game.core.entity.ext.SettingInfo;
import com.douqu.game.core.entity.ext.data.BaseData;
import com.douqu.game.core.entity.world.map.SpritePlayerBean;
import com.douqu.game.core.factory.DataFactory;
import com.douqu.game.core.factory.WorldInfoFactory;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.util.LogUtils;
import com.douqu.game.core.util.MapUtils;

import java.util.*;

/**
 * @Author: Bean
 * @Description:
 * @Date: 2018-06-22 16:23
 */
public class WorldMapKillData extends BaseData {

    /** 历史  上周  本周*/
    private Map<Integer,WorldMapKillBean> rewardList;

    /** 每日第一次进入 为true */
    private boolean firstEnter;

    private Player player;

    /** 膜拜玩家的列表 */
    private List<String> worshipList;

    /*******************以下数据仅用于当前计算 不进行数据库存储****************************/
    /** 当前击杀玩家的次数  防刷 */
    private Map<String,Integer> skillNumber;

    private Map<Integer,HegemonyResultItem> items;

    /** 是否大结算 */
    private boolean isBigSettle;

    private int totalScore;

    /**
     * 药品使用记录
     */
    private Map<Integer,Integer> reviceUseTimes;

    /*************************************************************************************/

    public WorldMapKillData(Player player){
        this.player = player;
        initReward();
        firstEnter = true;
        worshipList = new ArrayList<>();
        initCurrent();
    }

    @Override
    public void init() {
        initReward();
        firstEnter = true;
        worshipList = new ArrayList<>();
        initCurrent();
    }

    @Override
    public void checkInit() {
    }

    @Override
    public void reset() {
        firstEnter = true;
        worshipList.clear();
    }

    @Override
    public void checkReset() {
        reset();
    }

    public void initReward(){
        rewardList = new HashMap<>();
        WorldMapKillBean killBean = null;
        for (E_WorldMapKillRankType rankType:E_WorldMapKillRankType.values()){
            killBean = new WorldMapKillBean();
            rewardList.put(rankType.getCode(),killBean);
        }
    }

    public void initCurrent(){
        skillNumber = new HashMap<>();
        isBigSettle = false;
        totalScore = 0;
        initItems();
    }

    public void initItems(){
        items = new HashMap<>();
        HegemonyResultItem item = null;
        for (SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE itemType:SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.values()){
            if (itemType != SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.UNRECOGNIZED
                    && itemType != SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_UNKNOWN){
                item = new HegemonyResultItem();
                item.setType(itemType.getNumber());
                items.put(itemType.getNumber(), item);
            }
        }
    }

    public void loadFrom(ByteBuffer buffer)
    {
        int len = buffer.readByte();
        WorldMapKillBean killBean = null;
        Integer key = null;
        for (int i = 0; i < len;i ++){
            key = buffer.readByte();
            killBean = new WorldMapKillBean();
            killBean.loadFrom(buffer);
            rewardList.put(key,killBean);
        }

        firstEnter = buffer.readBoolean();

        len = buffer.readByte();
        for (int i = 0;i < len;i ++){
            worshipList.add(buffer.readUTF());
        }

        len = buffer.readByte();
        for (int i = 0;i < len;i++){
            skillNumber.put(buffer.readUTF(), buffer.readByte());
        }

        len = buffer.readByte();
        HegemonyResultItem item = null;
        for (int i = 0; i < len ; i ++){
            key =buffer.readByte();
            item = new HegemonyResultItem();
            item.loadFrom(buffer);
            items.put(key, item);
        }

        totalScore = buffer.readInt();
    }

    public void writeTo(ByteBuffer buffer)
    {

        buffer.writeByte(rewardList.size());
        for (Map.Entry<Integer,WorldMapKillBean> entry:rewardList.entrySet()){
            buffer.writeByte(entry.getKey());
            entry.getValue().writeTo(buffer);
        }

        buffer.writeBoolean(firstEnter);

        buffer.writeByte(worshipList.size());
        for (String playerIndex:worshipList){
            buffer.writeUTF(playerIndex);
        }

        buffer.writeByte(skillNumber.size());
        for (Map.Entry<String,Integer> entry:skillNumber.entrySet()){
            buffer.writeUTF(entry.getKey());
            buffer.writeByte(entry.getValue());
        }

        buffer.writeByte(items.size());
        for (Map.Entry<Integer,HegemonyResultItem> entry:items.entrySet()){
            buffer.writeByte(entry.getKey());
            entry.getValue().writeTo(buffer);
        }

        buffer.writeInt(totalScore);
    }

    /**
     * 每周日凌晨执行
     * @return
     */
    public boolean checkMonday()
    {
        WorldMapKillBean bean = rewardList.get(E_WorldMapKillRankType.CURRENT_WEEK_RANK.getCode());
        if (bean == null)
        {
            bean = new WorldMapKillBean();
            rewardList.put(E_WorldMapKillRankType.CURRENT_WEEK_RANK.getCode(),bean);
        }
        WorldMapKillBean lastBean = rewardList.get(E_WorldMapKillRankType.LAST_WEEK_RANK.getCode());
//        if (bean.getTotalValue() <= 0 || (lastBean == null || lastBean.getTotalValue() <= 0)){
//            /**
//             * 这里的意义是如果玩家本周没有进行争霸赛就没有必要进行
//             */
//            flag = false;
//        }
        rewardList.put(E_WorldMapKillRankType.LAST_WEEK_RANK.getCode(), bean);
        rewardList.put(E_WorldMapKillRankType.CURRENT_WEEK_RANK.getCode(),new WorldMapKillBean());
        return bean.getTotalValue() <= 0 && (lastBean == null || lastBean.getTotalValue() <= 0);
    }

    /**
     * 增加重复击杀统计 并返回当前数量
     * @param beKillBean
     * @return
     */
    public int addSkillNumber(WorldMapBeKillBean beKillBean){
        Integer number = skillNumber.get(beKillBean.getPlayerIndex());
        if (number == null){
            number = 1;
        }else{
            number ++;
        }
        skillNumber.put(beKillBean.getPlayerIndex(),number);
        return number;
    }

    /**
     * 获取当前的连杀数
     * @return
     */
    public int getSkillCount(){
        int count = 0;
        for (Map.Entry<String,Integer> entry:skillNumber.entrySet()){
            count += entry.getValue();
        }
        return count;
    }

    /** 击杀 */
    public HegemonyScoreChangeBean win(WorldMapBeKillBean beKillBean, String masterPlayerIndex)
    {
        /**
         * 1.获取重复击杀的数量
         * 2.获取基础分 倍率 等级差倍率 重复击杀倍率 vip加成 等基础数据
         * 3.得到连杀得分
         * 4.计算诛杀得分
         * 5.通知得分变化
         * 6.在item中保存 连杀与诛杀信息
         */
        int changeScore = 0;
        //连杀得分
        int skillScore = 0;
        //第几次杀这个玩家了
        int skillNumber = addSkillNumber(beKillBean);
        //获取 repeatMulRate 一定要在 baseScore之前
        int repeatMulRate = MapUtils.getRepeatMulRate(skillNumber);
        //连杀基础分增加npc类型的减少分数
        int baseScore = MapUtils.getBaseScore(getSkillCount(),beKillBean.getBeKillCount() < 0?true:false);
        //倍率由玩家等级修改为玩家支线等级
        int mulRate = MapUtils.getMulRate(player);
        int lvDifMulRate = MapUtils.getLvDifMulRate(player.getLv() - beKillBean.getLv());
        int campCity = 1;//阵营夺城
        int otherScore = 0;//额外积分
        int usePropId = player.getExtInfo(SettingInfo.class).getAutoRecover().getMilitaryPropId();
        if (usePropId != 0){
            /** 增加使用道具的连杀分 */
            PropConfig propConfig = DataFactory.getInstance().getGameObject(DataFactory.PROP_KEY,usePropId);
            if (propConfig != null){
                otherScore = propConfig.effectValue;
            }
        }
        skillScore = (int)(((double)baseScore * mulRate * lvDifMulRate/MapUtils.ONE_HUNDRED * repeatMulRate/MapUtils.ONE_HUNDRED + otherScore) * ((double)campCity));
        /**
         * 这里特别处理 击杀玩家最少给一分
         */
        if (skillScore == 0){
            skillScore = 1;
        }
        LogUtils.debug("skillScore:baseSocre:" + baseScore + " * mulRate:" + mulRate + " * lvDifMulRate/100:" + lvDifMulRate + " * repeatMulRate/100:" + repeatMulRate + " + otherScore：" + otherScore + " = " + skillScore);
        //诛杀得分
        /**
         * 诛杀如果杀的是重复玩家不在增加诛杀分
         */
        int doubleKillScore = 0;
        if (skillNumber == 1)
            doubleKillScore = MapUtils.getKillAndKillScore(beKillBean);
        LogUtils.debug("doubleKillScore:" + doubleKillScore);
        changeScore = skillScore + doubleKillScore;
        totalScore += changeScore;
        //判断是否掉落道具
        dropProp(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_EVENSKILL, masterPlayerIndex);

        HegemonyResultObject skillObject = new HegemonyResultObject();
        skillObject.setTitle("X" + getSkillCount());
        skillObject.setNum(beKillBean.getLv());
        skillObject.setScore(skillScore);
        items.get(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_EVENSKILL.getNumber()).addObjects(skillObject);
        items.get(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_EVENSKILL.getNumber()).addAddition(otherScore);
        //诛杀分数大于0的 才统计到诛杀列表中
        if (doubleKillScore > 0){
            HegemonyResultObject doubleObject = new HegemonyResultObject();
            doubleObject.setTitle(beKillBean.getName());
            doubleObject.setNum(beKillBean.getBeKillCount());
            doubleObject.setScore(doubleKillScore);
            items.get(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_KILLANDKILL.getNumber()).addObjects(doubleObject);
        }
        //返回分数变化信息
        HegemonyScoreChangeBean changeBean = new HegemonyScoreChangeBean();
        changeBean.setType(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_EVENSKILL.getNumber());
        //如果是复活的话 value 表示复活
        changeBean.setValue(getSkillCount());
        changeBean.setScore(totalScore);
        changeBean.setChangeScore(changeScore);
        return changeBean;
    }

    /** 失败  回城就调用这个方法 和被击杀没有关系 */
    public void lose(String masterPlayerIndex)
    {
        //第一场就失败 不计算总分
        if (getSkillCount()  == 0){
            return;
        }
        int vipRate = MapUtils.getVipMulRate(player);
        totalScore = (int)(totalScore * (((double)vipRate + 100)/100));
        isBigSettle = record(masterPlayerIndex);

        HegemonyResultItem resultItem = items.get(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_EVENSKILL.getNumber());
        resultItem.setRate(MapUtils.getMulRate(player));
    }

    /**
     * 使用复活道具
     */
    public void useReviveProp(SGCommonProto.E_REVIVE_TYPE reviveType){

    }

    /**
     * 占领城市
     * @param cityType
     */
    public HegemonyScoreChangeBean captureCity(SGCommonProto.E_CITY_TYPE cityType){

        int value = MapUtils.getCityScore(cityType);
        int campCity = 1;//阵营夺城
        final int changeScore = (int)((double)value * ((double)campCity));
        LogUtils.debug("cityScore:" + value );

        totalScore += changeScore;

        HegemonyResultObject cityObject = new HegemonyResultObject();
        switch (cityType){
            case CITY_TYPE_CAPITAL:
                cityObject.setTitle("首都");
                break;
            case CITY_TYPE_SUBCAPITAL:
                cityObject.setTitle("大城");
                break;
            case CITY_TYPE_PASS:
                cityObject.setTitle("关卡");
                break;
            case CITY_TYPE_NORMAL:
                cityObject.setTitle("小城");
                break;
            default:
                break;
        }
        List<HegemonyResultObject> objectList = items.get(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_CITY.getNumber()).getObjects();

        if (objectList.contains(cityObject)){
            objectList.forEach(o -> {
                if (o.equals(cityObject)){
                    o.addNum();
                    o.addScore(changeScore);
                }
            });
        }else{
            cityObject.setNum(1);
            cityObject.setScore(changeScore);
            objectList.add(cityObject);
        }
        HegemonyScoreChangeBean changeBean = new HegemonyScoreChangeBean();
        changeBean.setType(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_CITY.getNumber());
        changeBean.setValue(getCityCount());
        changeBean.setScore(totalScore);
        changeBean.setChangeScore(changeScore);
        return changeBean;
    }

    public int getCityCount(){
        HegemonyResultItem item = items.get(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_CITY.getNumber());
        if (item == null || item.getObjects() == null){
            return 0;
        }
        return item.getObjects().size();
    }

    public HegemonyScoreChangeBean useMilitary(List<PropConfig> propConfigList){
        HegemonyScoreChangeBean changeBean = new HegemonyScoreChangeBean();
        changeBean.setType(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_CAPITAL.getNumber());
        HegemonyScoreChangeBean builder;
        for (PropConfig propConfig:propConfigList){
            builder = useMilitary(propConfig,1);
            changeBean.setValue(builder.getValue());
            changeBean.setScore(builder.getScore());
            changeBean.setChangeScore(changeBean.getChangeScore() + builder.getChangeScore());
        }
        return changeBean;
    }

    /**
     * 获得军资
     * @param propConfig
     */
    public HegemonyScoreChangeBean useMilitary(PropConfig propConfig,int count){

        int value = propConfig.effectValue;
        int campCity = 1;//阵营夺城
        final int changeScore = (int)((double)value * count * ((double)campCity));
        LogUtils.debug("militaryScore:" + value);
        HegemonyResultObject propObject = new HegemonyResultObject();
        propObject.setTitle(String.valueOf(propConfig.id));
        List<HegemonyResultObject> objectList = items.get(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_CAPITAL.getNumber()).getObjects();
        if (objectList.contains(propObject)){
            objectList.forEach(o -> {
                if (propObject.equals(o)){
                    o.addNum();
                    o.addScore(changeScore);
                }
            });
        }else{
            propObject.setNum(1);
            propObject.setScore(changeScore);
            objectList.add(propObject);
        }

        totalScore += changeScore;

        HegemonyScoreChangeBean changeBean = new HegemonyScoreChangeBean();
        changeBean.setType(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_CAPITAL.getNumber());
        changeBean.setValue(propConfig.id);
        changeBean.setScore(totalScore);
        changeBean.setChangeScore(changeScore);
        return changeBean;
    }

    /**
     * 大结算的两种情况
     * 1.单次积分突破历史最高记录  弹出
     * 2.单次连杀数达到不使用道具记录的前一档次 弹出
     * @return
     */
    private boolean record(String masterPlayerIndex)
    {
        //判断是否达到本周记录
        WorldMapKillBean current = rewardList.get(E_WorldMapKillRankType.CURRENT_WEEK_RANK.getCode());
        //不使用道具
        SpritePlayerBean bean = WorldInfoFactory.getInstance().getWorldMapData(masterPlayerIndex).getPlayerActionBean(player.objectIndex);
        if (bean == null){
            return false;
        }
        boolean prop = player.getExtInfo(SettingInfo.class).getAutoRecover().wasUseItem();
        if (!prop){
            if (totalScore >= current.getNoPropMaxValue()){
                current.setNoPropMaxValue(totalScore);
            }
            if (getSkillCount() > current.getNoPropSkills()){
                current.setNoPropSkills(getSkillCount());
            }
        }
        //最高分
        if (totalScore >= current.getMaxValue()){
            current.setMaxValue(totalScore);
        }
        if (getSkillCount() >= current.getSkills()){
            current.setSkills(getSkillCount());
        }
        current.addTotal(totalScore);
        //是否达到记录
        boolean flag = false;
        WorldMapKillBean history = rewardList.get(E_WorldMapKillRankType.HISTORY_RANK.getCode());
        if (!prop){
            if (totalScore >= history.getNoPropMaxValue()){
                history.setNoPropMaxValue(totalScore);
            }
            if (getSkillCount() > history.getNoPropSkills()){
                history.setNoPropSkills(getSkillCount());
            }
        }
        if (totalScore >= history.getMaxValue()){
            history.setMaxValue(totalScore);
            //分数上的突破
            flag = true;
        }
        if (getSkillCount() >= current.getSkills()){
            history.setSkills(getSkillCount());
        }
        //设定 现在大于15次才可能出现大结算

        //五是一个等级
        int fiveCountRecord = history.getNoPropSkills()/5;
        int currentCountRecord = totalScore/5;
        if (currentCountRecord > 3 && (currentCountRecord + 1) >= fiveCountRecord){
            flag = true;
        }
        return flag;
    }

    //获取玩家总分最高记录
    public int getTotalValue(E_WorldMapKillRankType type){
        return rewardList.get(type.getCode()).getTotalValue();
    }

    public int getMaxValue(E_WorldMapKillRankType type){
        return rewardList.get(type.getCode()).getMaxValue();
    }

    public int getHistorySkillCount(){
        return rewardList.get(E_WorldMapKillRankType.HISTORY_RANK.getCode()).getSkills();
    }

    public TwoTuple<Map<SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE,SGCommonProto.HegemonyResultItem.Builder>,Boolean> getSettleInfo(){
        TwoTuple<Map<SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE,SGCommonProto.HegemonyResultItem.Builder>,Boolean> twoTuple =
                new TwoTuple<>();

        twoTuple.setFirst(itemsToProtoBuf());
        twoTuple.setSecond(isBigSettle);
        return twoTuple;
    }

    public Map<SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE,SGCommonProto.HegemonyResultItem.Builder> itemsToProtoBuf(){
        Map<SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE,SGCommonProto.HegemonyResultItem.Builder> map = new HashMap<>();
        for (Map.Entry<Integer,HegemonyResultItem> entry:items.entrySet()){
            if (entry.getValue().getObjects().size() == 0){
                //如果没有值continue
                continue;
            }
            SGCommonProto.HegemonyResultItem.Builder b = SGCommonProto.HegemonyResultItem.newBuilder();
            b.setType(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.forNumber(entry.getValue().getType()));
            b.setAddition(entry.getValue().getAddition());
            b.setRate(entry.getValue().getRate());
            //倒序
            if (entry.getKey() == SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_EVENSKILL_VALUE){
                Collections.reverse(entry.getValue().getObjects());
            }
            for (HegemonyResultObject object: entry.getValue().getObjects()){
                SGCommonProto.HegemonyResultObject.Builder o = SGCommonProto.HegemonyResultObject.newBuilder();
                o.setTitle(object.getTitle());
                o.setNum(object.getNum());
                o.setScore(object.getScore());
                b.addObjects(o);
            }
            map.put(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.forNumber(entry.getKey()),b);
        }
        return map;
    }

    /**
     * 是否已经对该玩家进行过膜拜
     * @param playerIndex
     * @return
     */
    public boolean isAlreadyWorship(String playerIndex){
        for (String pi:worshipList){
            if (playerIndex.equals(pi)){
                return false;
            }
        }
        return true;
    }

    /**
     * 获取当前结算积分
     * @return
     */
    public int getCurrentTotalScore(){
        return totalScore;
    }

    /***
     * 获取vip加成
     * @return
     */
    public int getVipPlus(){
        VipConfig vipConfig = DataFactory.getInstance().getGameObject(DataFactory.VIP_KEY,player.getVipLevel());
        return vipConfig.hegemonyMul;//vip倍率
    }

    /**
     * 获取阵营夺城  TOO DO
     * @return
     */
    public int campScore(){
        return 0;
    }

    /************** 掉落道具 **************/
    public void dropProp(SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE type, String masterPlayerIndex){
        CityDropGroupConfig config = null;
        /**
         * 1.获取玩家当前的杀人数
         * 2.读取配置表判断是否掉落
         */
        switch (type.getNumber()){
            case SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_EVENSKILL_VALUE:
                //连杀
                config =  MapUtils.getDropGroupConfig(E_CityDrop_Flush_Type.CITY_DROP_FLUSH_EVEBKILL,getSkillCount());
                break;
            case SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_CITY_VALUE:
                //夺城
                break;
            case SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_KILLANDKILL_VALUE:
                //诛杀
                break;
            case SGCommonProto.E_MAPINTEGRAL_SETTLE_TYPE.WORLD_MAP_INTEGRAL_SETTLE_CAPITAL_VALUE:
                //军资
                break;
        }
        if (config != null){
            WorldInfoFactory.getInstance().getWorldMapData(masterPlayerIndex).cityDrop(config, SGCommonProto.E_CAMP_TYPE.forNumber(player.camp), player.getObjectIndex());
        }
    }

    public WorldMapKillBean getWorldMapKillBean(E_WorldMapKillRankType type){
        return rewardList.get(type.getCode());
    }

    public boolean isFirstEnter() {
        if (firstEnter){
            firstEnter = false;
            return true;
        }
        return firstEnter;
    }

    public void addWorship(String playerIndex){
        if (worshipList == null){
            worshipList = new ArrayList<>();
        }
        worshipList.add(playerIndex);
    }

    public WorldMapKillBean getKillBean(E_WorldMapKillRankType rankType)
    {
        return rewardList.get(rankType.getCode());
    }

}
